<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/25 0025
 * Time: 下午 3:48
 */

namespace common\components;


class Rsa
{
    private $privateKey;
    private $publicKey;
    private $keyLen;

    public function __construct($privateKey, $publicKey)
    {
        $this->privateKey = $this->_getContents($privateKey);
        $this->publicKey = $this->_getContents($publicKey);

        $publicKey = $this->_getPublicKey();
        $this->keyLen = openssl_pkey_get_details($publicKey)["bits"];
        openssl_free_key($publicKey);
    }

    /**
     * @uses 获取文件内容
     * @param $fileContent string
     * @return bool|string
     */
    private function _getContents($fileContent)
    {
        if ( is_file($fileContent) || strpos($fileContent, "http") !== false ) {
            return file_get_contents($fileContent);
        }
        return $fileContent;
    }

    /**
     * @uses 获取私钥
     * @return bool|resource
     */
    private function _getPrivateKey()
    {
        return openssl_pkey_get_private($this->privateKey);
    }

    /**
     * @uses 获取公钥
     * @return bool|resource
     */
    private function _getPublicKey()
    {
        return openssl_pkey_get_public($this->publicKey);
    }

    /**
     * @uses 私钥加密
     * @param string $data
     * @return null|string
     */
    public function privateEncrypt($data = '') {
        if ( !is_string($data) ) {
            return null;
        }
        $encrypted = "";
        $tmpEncrypted = "";
        $partLen = $this->keyLen / 8 - 11;
        $data = str_split($data, $partLen);
        $privateKey = $this->_getPrivateKey();
        foreach ( $data as $item ) {
            openssl_private_encrypt($item, $tmpEncrypted, $privateKey);#die(var_dump($data));
            $encrypted .= $tmpEncrypted;
        }
        openssl_free_key($privateKey);
        return $encrypted;#base64_encode($encrypted);
    }

    /**
     * @uses 公钥加密
     * @param string $data
     * @return null|string
     */
    public function publicEncrypt($data = "")
    {
        if (!is_string($data)) {
            return null;
        }
        $encrypted = "";
        $tmpEncrypted = "";
        $partLen = $this->keyLen / 8 - 11;
        $data = str_split($data, $partLen);
        $publicKey = $this->_getPublicKey();
        foreach ( $data as $item ) {
            openssl_public_encrypt($item, $tmpEncrypted, $publicKey);#die(var_dump($data));
            $encrypted .= $tmpEncrypted;
        }
        openssl_free_key($publicKey);
        return $encrypted;
    }

    /**
     * @uses 私钥解密
     * @param string $encrypted
     * @return null
     */
    public function privateDecrypt($encrypted = '')
    {
        if (!is_string($encrypted)) {
            return null;
        }#die($encrypted);
        $decrypted = "";
        $tmpDecrypted = "";
        $privateKey = $this->_getPrivateKey();
        $partLen = $this->keyLen / 8;
        foreach ( str_split($encrypted, $partLen) as $chunk ) {
            $res = openssl_private_decrypt($chunk, $tmpDecrypted, $privateKey);
            if ( !$res ) {
                echo openssl_error_string()."\r\n";
            }
            $decrypted .= $tmpDecrypted;
        }
        openssl_free_key($privateKey);
        return $decrypted;
    }

    /**
     * @uses 公钥解密
     * @param string $encrypted
     * @return null
     */
    public function publicDecrypt($encrypted = '')
    {
        if (!is_string($encrypted)) {
            return null;
        }
        $decrypted = "";
        $tmpDecrypted = "";
        $publicKey = $this->_getPublicKey();
        $partLen = $this->keyLen / 8 - 11;
        foreach (str_split($encrypted, $partLen) as $chunk) {
            openssl_public_decrypt($chunk, $tmpDecrypted, $publicKey);
            $decrypted .= $tmpDecrypted;
        }
        openssl_free_key($publicKey);
        return $decrypted;
    }

    public static function formatPublicKey($publicKey)
    {
        $publicKey = str_replace("-----BEGIN PUBLIC KEY-----","", $publicKey);
        $publicKey = str_replace("-----END PUBLIC KEY-----","", $publicKey);
        $publicKey = str_replace("\n","", $publicKey);

        $publicKey = '-----BEGIN PUBLIC KEY-----'.PHP_EOL.wordwrap($publicKey, 64, "\n", true) .PHP_EOL.'-----END PUBLIC KEY-----';
        return $publicKey;
    }

    public static function formatPrivateKey($privateKey)
    {
        $privateKey = str_replace("-----BEGIN RSA PRIVATE KEY-----","", $privateKey);
        $privateKey = str_replace("-----END RSA PRIVATE KEY-----","", $privateKey);
        $privateKey = str_replace("\n","",$privateKey);

        $privateKey = '-----BEGIN RSA PRIVATE KEY-----'.PHP_EOL.wordwrap($privateKey, 64, "\n", true) .PHP_EOL.'-----END RSA PRIVATE KEY-----';
        #file_put_contents("D://temp.txt", $privateKey);
        return $privateKey;
    }

    public static function url_safe_base64_encode ($data) {
        return str_replace(array('+','/', '='),array('-','_', ''), base64_encode($data));
    }

    public static function url_safe_base64_decode ($data) {
        $base_64 = str_replace(array('-','_'),array('+','/'), $data);
        return base64_decode($base_64);
    }

}